#pragma once
#include "Common.hpp"
#include "Command.hpp"
#include "Socket.hpp"
#include <sys/wait.h>
#include <functional>

using namespace MySocket;

using servicefunc_t = std::function<void(std::shared_ptr<Socket>&,InetAddr&)>;

class TcpServer : public Nocopy
{
public:
    TcpServer(uint16_t port,servicefunc_t servic):
    _port(port),
    _listensockfdptr(std::make_unique<TcpSocket>()),
    _isrunning(false),
    _service(servic)
    {
        _listensockfdptr->BuildSocket(_port);
    }
    
    void Start()
    {
        _isrunning = true;
        while(_isrunning)
        {
            InetAddr client;
            auto sock = _listensockfdptr->Accept(&client);
            if(sock==nullptr)
                continue;
            LOG(Loglevel::DEBUG) << "accept success";

            pid_t pid = fork();
            if(pid>0)
            {
                pid = fork();
                if(pid>0)
                    exit(OK);
                //func
                _service(sock,client);
                exit(OK);
            }
            else if(pid==0)
            {
                sock->Close();
                pid_t rid = waitpid(pid,nullptr,0);
                (void)rid;
            }
            else 
            {
                LOG(Loglevel::FATAL) << "fork error";
                exit(FORK_ERROR);
            }
        }
    }

    ~TcpServer(){}
private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensockfdptr;
    bool _isrunning;
    servicefunc_t _service;
};
